package com.moonshine.parser.finder;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.moonshine.parser.models.AS3Signature;
import com.moonshine.parser.models.ClassBaseSignature;
import com.moonshine.parser.models.ClassSignature;
import com.moonshine.parser.models.Flags;
import com.moonshine.parser.models.InterfaceSignature;
import com.moonshine.parser.models.MethodSignature;
import com.moonshine.parser.models.VariableSignature;

public class RealTimeClassInfoDB extends ClassInfoDB {

	public final static String COMPLETE_PUBLIC = "public";
	public final static String COMPLETE_PROTECTED = "protected";

	public RealTimeClassInfoDB() {
		// TODO Auto-generated constructor stub
	}

	private ClassBaseSignature activeClassSignature;

	boolean inProcessingMode;
	private boolean isResolving;

	@Override
	protected void processClassSignature(ClassBaseSignature classSig) {

		final Boolean isClassSignature = classSig instanceof ClassSignature;
		if (activeClassSignature == null) {
			activeClassSignature = classSig;
		} else if (isResolving) {
			final int flags = Flags.ACCESS_PROTECTED | Flags.ACCESS_PUBLIC;
			addSignatures(activeClassSignature.methods, classSig.methods, flags);

			if (isClassSignature)
				addSignatures(
						((ClassSignature) activeClassSignature).variables,
						((ClassSignature) classSig).variables, flags);

		}

		List<String> extendedFrom = new ArrayList<String>();

		if (isClassSignature) {
			String extendedClass = ((ClassSignature) classSig).extendedFrom;
			if (extendedClass != null && extendedClass != "")
				extendedFrom.add(extendedClass);
		} else {

			extendedFrom = ((InterfaceSignature) classSig).extendedFrom;
		}

		// Index extended class/interface first
		for (String extendedClass : extendedFrom) {
			File extendedClassFile = findClassFilePath(classSig, extendedClass);
			if (extendedClassFile != null)
				indexClassFile(extendedClassFile);
		}

	}

	@Override
	public String resolveType(String qualifedClassName, String property)
			throws IOException {
		// TODO Auto-generated method stub
		isResolving = true;
		activeClassSignature = null;
		String type = "Object";
		final File foundClassFile = findClassFilePath(qualifedClassName);
		if (foundClassFile != null) {
			indexClassFile(foundClassFile);
		}

		if (activeClassSignature != null) {
			if (activeClassSignature instanceof ClassSignature) {
				final ClassSignature classSig = (ClassSignature) activeClassSignature;
				if (classSig.variables.size() != 0) {
					final List<VariableSignature> varSigs = classSig.variables;
					resolveClassVariableTypes(classSig, varSigs);
					type = findPropertyType(varSigs, property);
				}
			} else if (activeClassSignature instanceof InterfaceSignature) {

				type = findMethodReturnType(activeClassSignature, property);

			}
		}
		isResolving = false;
		// TODO: Query DB or cache layer
		return type;
	}

	private String findMethodReturnType(ClassBaseSignature classSig, String name)
			throws IOException {
		// TODO Auto-generated method stub
		for (MethodSignature methodSig : classSig.methods) {
			if (methodSig.name.equals(name)) {

				return resolveClassVariableTypes(classSig, methodSig.returnType);
			}
		}
		return "void";
	}

	public List<AS3Signature> resolveCompletionList(String forClass, int flags) {
		isResolving = true;
		activeClassSignature = null;
		final File foundClassFile = findClassFilePath(forClass);
		if (foundClassFile != null) {

			indexClassFile(foundClassFile);
		}
		List<AS3Signature> completions = new ArrayList<AS3Signature>();
		if (activeClassSignature != null) {
			if (activeClassSignature instanceof ClassSignature) {
				addSignatures(completions,
						((ClassSignature) activeClassSignature).variables,
						flags);
			}

			addSignatures(completions, activeClassSignature.methods, flags);
		}
		isResolving = false;
		return completions;
	}

	@SuppressWarnings("unchecked")
	protected void addSignatures(List<? extends AS3Signature> list,
			List<? extends AS3Signature> sigs, int flags) {
		final List<AS3Signature> out = (List<AS3Signature>) list;
		final Iterator<AS3Signature> itr = (Iterator<AS3Signature>) sigs
				.iterator();
		AS3Signature sig;
		while (itr.hasNext()) {
			sig = (AS3Signature) itr.next();
			if (AS3Signature.checkFlag(sig.access, flags))
				out.add(sig);
		}
	}

	protected String findPropertyType(List<VariableSignature> varSigs,
			String name) {

		for (VariableSignature varSig : varSigs) {

			if (varSig.name.equals(name))
				return varSig.declaredType;

		}

		return "Object";
	}
}
